package com.kehutong.contact.admin;

import com.kehutong.common.DoveClient;
import com.kehutong.common.constant.CommonConstant;
import com.kehutong.common.entity.Root;
import com.kehutong.common.errcode.Result;
import com.kehutong.common.interceptor.TrasIntercepter;
import com.kehutong.common.permission.UserLoginInfo;
import com.kehutong.common.util.Token;
import com.kehutong.contact.entity.Resident;
import com.kehutong.contact.entity.ResidentCar;
import com.kehutong.contact.entity.ResidentFamily;
import com.kehutong.contact.entity.ResidentHouse;
import com.kehutong.contact.enums.BindType;
import com.kehutong.contact.enums.HouseType;
import com.kehutong.contact.enums.ResidentType;
import com.kehutong.contact.service.DataPvService;
import com.kehutong.contact.service.impl.ResidentServiceImpl;
import com.kehutong.contact.util.ExcelUtil;
import com.kehutong.contact.util.ResidentTagUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.coraframework.authz.HasPermission;
import org.coraframework.authz.Subject;
import org.coraframework.authz.SubjectUtil;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.MvcAction;
import org.coraframework.mvc.http.Bean;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.entity.FindArray;
import org.coraframework.orm.jdbc.execute.entity.FindOne;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.util.Objects;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 住户控制器
 *
 * @Author: liukunlong
 * @Date: 21/2/8 上午9:43
 */
@MvcAction
@ReqMapping("/admin/crm/resident")
public class ResidentController {

    static final Logger logger = LoggerFactory.getLogger(ResidentController.class);

    @Inject
    private ResidentServiceImpl residentService;


    @Inject
    private JdbcSession jdbcSession;

    @Inject
    private DoveClient doveClient;

    @Inject
    private DataPvService dataPvService;

    @ReqMapping("/groupResident")
    public Object groupResident(JSONObject jsonObject){
        List<ResidentHouse> residentHouses = jdbcSession.findArray(ResidentHouse.class)
                .eq(jsonObject, "houseNo")
                .in("bindType",BindType.NO_BIND,BindType.BIND)
                .eq("deleted", false)
                .exe();

        List<String> residentNos = residentHouses.stream().map(ResidentHouse::getResidentNo).collect(Collectors.toList());

        List<Resident> residents = jdbcSession.findArray(Resident.class)
                .in("id", residentNos)
                .exe();

        List<JSONObject> result = new ArrayList<>();
        for (ResidentType type: ResidentType.values()) {
            JSONObject json = new JSONObject();
            json.put("name", type.getDesc());
            json.put("id", type.getId());

            List<JSONObject> list = new ArrayList<>();
            residents.forEach(item -> {
                if(Objects.equal(item.getType(), type)){
                    JSONObject temp = new JSONObject();
                    temp.put("id", item.getId());
                    temp.put("name", item.getRealname());
                    list.add(temp);
                }
            });
            json.put("data", list);
            result.add(json);
        }

        return result;
    }

    /**
     * 新增或变更房屋业主信息
     *
     * @param resident 住户对象
     * @return 结果
     * @throws Exception 异常
     */
    @Bean(newInstance = true, copy = true)
    @HasPermission("crm:resident:edit")
    @ReqMapping("/saveOrUpdateHouseOwner")
    public Object saveOrUpdateHouseOwner(Token token, Resident resident) throws Exception {
        resident.setCompanyNo(token.getCompanyNo());
        resident.setCompanyName(token.getCompanyName());
        resident.setCreateBy(token.getUuid());
        resident.setCreateName(token.getUsername());
        return residentService.saveOrUpdateHouseOwner(resident);
    }

    /**
     * 根据条件获取住户列表
     *
     * @param jsonObject 查询对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @HasPermission("crm:resident:view")
    @ReqMapping("/getResidentList")
    public Object getResidentList(JSONObject jsonObject) throws Exception {
        Page<Resident> page = residentService.getResidentList(jsonObject);
        return Result.success(page);
    }



    /**
     * 获取住户标签统计报表
     *
     * @param jsonObject 查询对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @HasPermission("crm:resident:view")
    @ReqMapping("/getResidentTagReport")
    public Object getResidentTagReport(Token token, JSONObject jsonObject) throws Exception {
        //获取住户的跟进记录 todo 需要测试
        JSONObject tagResult = doveClient.post("/crm/tag/getTagList", (http) -> {
            http.addHeader("companyNo", token.getCompanyNo());
            http.addParam("pid", Root.ROOT_ID);
        });
        JSONArray tagList = tagResult.getJSONObject("data").getJSONArray("list");

        List<Map<String, Object>> tagListMap = new ArrayList<>();
        for (Object tagObj : tagList) {
            JSONObject tag = (JSONObject) tagObj;
            Map<String, Object> tagOneMap = new LinkedHashMap<>();
            tagOneMap.put("tagNo", tag.getString("id"));
            tagOneMap.put("tagName", tag.getString("name"));
            List<Map<String, Object>> childListMap = new ArrayList<>();
            JSONObject childTagResult = doveClient.post("/crm/tag/getTagList", (http) -> {
                http.addHeader("companyNo", token.getCompanyNo());
                http.addParam("pid", tag.getString("id"));
            });
            if (childTagResult.getIntValue("code") == 200) {
                JSONArray childTagList = childTagResult.getJSONObject("data").getJSONArray("list");
                for (Object childTagObj : childTagList) {
                    JSONObject childTag = (JSONObject) childTagObj;
                    Map<String, Object> tagTwoMap = new LinkedHashMap<>();
                    tagTwoMap.put("tagNo", childTag.getString("id"));
                    tagTwoMap.put("tagName", childTag.getString("name"));
                    childListMap.add(tagTwoMap);
                }
                tagOneMap.put("childList", childListMap);
            }
            tagListMap.add(tagOneMap);
        }
        List<Resident> residentList = residentService.getResidentList(jsonObject).getList();
        List<Map<String, Object>> result = ResidentTagUtil.sumTags(tagListMap, residentList);
        return Result.success(result);
    }

    /***
     * 根据住户标志获取住户信息
     * @param id 住户标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @HasPermission("crm:resident:view")
    @ReqMapping("/getResidentById")
    public Object getResidentById(String id) throws Exception {
        Resident resident = residentService.getResidentById(id);
        return Result.success(resident);
    }


    /**
     * 保存住户
     *
     * @param resident 住户对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    @HasPermission("crm:resident:edit")
    @ReqMapping("/saveResident")
    public Object saveResident(Token token, Resident resident) throws Exception {
        resident.setCompanyNo(token.getCompanyNo());
        resident.setCompanyName(token.getCompanyName());
        resident.setCreateBy(token.getUuid());
        resident.setCreateName(token.getUsername());
        residentService.saveResident(resident);
        return Result.success(resident);
    }


    /**
     * 更新住户
     *
     * @param resident 住户对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @TrasIntercepter("/crm/tag/getTagList")
    @Bean(copy = true)
    @HasPermission("crm:resident:edit")
    @ReqMapping("/updateResident")
    public Object updateResident(Token token, Resident resident) throws Exception {
        resident.setCompanyNo(token.getCompanyNo());
        resident.setCompanyName(token.getCompanyName());
        resident.setCreateBy(token.getUuid());
        resident.setCreateName(token.getUsername());
        residentService.updateResident(resident);
        return Result.success(resident);
    }


    /***
     * 根据住户标志删除住户信息
     * @param id 住户标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @HasPermission("crm:resident:edit")
    @ReqMapping("/deleteResidentById")
    public Object deleteResidentById(String id) throws Exception {
        residentService.deleteResidentById(id);
        return Result.success();
    }


    /**
     * 根据条件获取住户汽车列表
     *
     * @param jsonObject 查询对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    /*@HasPermission("crm:residentCar:view")*/
    @ReqMapping("/getResidentCarList")
    public Object getResidentCarList(JSONObject jsonObject) throws Exception {
        Page<ResidentCar> page = residentService.getResidentCarList(jsonObject);
        return Result.success(page);
    }


    /***
     * 根据住户汽车标志获取住户汽车信息
     * @param id 住户汽车标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    /*    @HasPermission("crm:residentCar:view")*/
    @ReqMapping("/getResidentCarById")
    public Object getResidentCarById(String id) throws Exception {
        ResidentCar residentCar = residentService.getResidentCarById(id);
        return Result.success(residentCar);
    }


    /**
     * 保存住户汽车
     *
     * @param residentCar 住户汽车对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    /*    @HasPermission("crm:residentCar:edit")*/
    @ReqMapping("/saveResidentCar")
    public Object saveResidentCar(ResidentCar residentCar) throws Exception {
        residentService.saveResidentCar(residentCar);
        return Result.success();
    }


    /**
     * 更新住户汽车
     *
     * @param residentCar 住户汽车对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @Bean(copy = true)
    //@HasPermission("crm:residentCar:edit")
    @ReqMapping("/updateResidentCar")
    public Object updateResidentCar(ResidentCar residentCar) throws Exception {
        residentService.updateResidentCar(residentCar);
        return Result.success();
    }


    /***
     * 根据住户汽车标志删除住户汽车信息
     * @param id 住户汽车标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    //@HasPermission("crm:residentCar:edit")
    @ReqMapping("/deleteResidentCarById")
    public Object deleteResidentCarById(String id) throws Exception {
        residentService.deleteResidentCarById(id);
        return Result.success();
    }


    /**
     * 根据条件获取住户家庭成员列表
     *
     * @param jsonObject 查询对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    //@HasPermission("crm:residentFamily:view")
    @ReqMapping("/getResidentFamilyList")
    public Object getResidentFamilyList(JSONObject jsonObject) throws Exception {
        Page<ResidentFamily> page = residentService.getResidentFamilyList(jsonObject);
        return Result.success(page);
    }


    /***
     * 根据住户家庭成员标志获取住户家庭成员信息
     * @param id 住户家庭成员标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    //@HasPermission("crm:residentFamily:view")
    @ReqMapping("/getResidentFamilyById")
    public Object getResidentFamilyById(String id) throws Exception {
        ResidentFamily residentFamily = residentService.getResidentFamilyById(id);
        return Result.success(residentFamily);
    }


    /**
     * 保存住户家庭成员
     *
     * @param residentFamily 住户家庭成员对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    //@HasPermission("crm:residentFamily:edit")
    @ReqMapping("/saveResidentFamily")
    public Object saveResidentFamily(ResidentFamily residentFamily) throws Exception {
        residentService.saveResidentFamily(residentFamily);
        return Result.success();
    }


    /**
     * 更新住户家庭成员
     *
     * @param residentFamily 住户家庭成员对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @Bean(copy = true)
    //@HasPermission("crm:residentFamily:edit")
    @ReqMapping("/updateResidentFamily")
    public Object updateResidentFamily(ResidentFamily residentFamily) throws Exception {
        residentService.updateResidentFamily(residentFamily);
        return Result.success();
    }


    /***
     * 根据住户家庭成员标志删除住户家庭成员信息
     * @param id 住户家庭成员标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    //@HasPermission("crm:residentFamily:edit")
    @ReqMapping("/deleteResidentFamilyById")
    public Object deleteResidentFamilyById(String id) throws Exception {
        residentService.deleteResidentFamilyById(id);
        return Result.success();
    }


    /**
     * 根据条件获取住户房屋列表
     *
     * @param jsonObject 查询对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    //@HasPermission("crm:residentHouse:view")
    @ReqMapping("/getResidentHouseList")
    public Page<ResidentHouse> getResidentHouseList(JSONObject jsonObject,Token token) throws Exception {
        //数据权限类型 1.全部 2.我管理的 3.下属管理的
        String dataPvType = jsonObject.getString("dataPvType");
        if (Objects.nonEmpty(dataPvType)) {
            //根据不同类型获取数据权限
            if (Objects.nonEmpty(dataPvType)) {
                List<String> assetsIdList=buildAssetsPv(dataPvType);

                if(Objects.isEmpty(assetsIdList)){
                    return new Page<>();
                }

                jsonObject.put("assetsIds",assetsIdList);
            }
        }
        return residentService.getResidentHouseList(jsonObject);
    }


    /***
     * 根据住户房屋标志获取住户房屋信息
     * @param id 住户房屋标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    // @HasPermission("crm:residentHouse:view")
    @ReqMapping("/getResidentHouseById")
    public Object getResidentHouseById(String id) throws Exception {
        ResidentHouse residentHouse = residentService.getResidentHouseById(id);
        return Result.success(residentHouse);
    }


    /**
     * 保存住户房屋
     *
     * @param residentHouse 住户房屋对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @Bean(newInstance = true, copy = true)
    //@HasPermission("crm:residentHouse:edit")
    @ReqMapping("/saveResidentHouse")
    public Object saveResidentHouse(ResidentHouse residentHouse) throws Exception {
        residentHouse.setBindType(BindType.NO_BIND);
        residentService.saveResidentHouse(residentHouse);
        return Result.success();
    }


    /**
     * 更新住户房屋
     *
     * @param residentHouse 住户房屋对象
     * @return 操作结果
     * @throws Exception 操作异常
     */
    @Bean(copy = true)
    //@HasPermission("crm:residentHouse:edit")
    @ReqMapping("/updateResidentHouse")
    public Object updateResidentHouse(ResidentHouse residentHouse) throws Exception {
        residentService.updateResidentHouse(residentHouse);
        return Result.success();
    }


    /***
     * 根据住户房屋标志删除住户房屋信息
     * @param id 住户房屋标志
     * @return 操作结果
     * @throws Exception 操作异常
     */
    //@HasPermission("crm:residentHouse:edit")
    @ReqMapping("/deleteResidentHouseById")
    public Object deleteResidentHouseById(String id) throws Exception {
        residentService.deleteResidentHouseById(id);
        return Result.success();
    }

    /**
     * 根据条件导出住户数据
     *
     * @param jsonObject
     * @return
     * @throws Exception
     */
    @ReqMapping("/exportResidentData")
    public Object exportResidentData(JSONObject jsonObject) throws Exception {
        Page<Resident> page = residentService.getResidentList(jsonObject);
        File residentDataFile = residentService.exportResidentDataFile(page.getList());
        return Result.download(residentDataFile);
    }

    private List<String> buildAssetsPv(String dataPvType) throws Exception {
        List<String> result = new ArrayList<>();
        Subject subject = SubjectUtil.getSubject();
        UserLoginInfo userLoginInfo = subject.getAttr(CommonConstant.CURRENT_USER_INFO + ":" + subject.getUserId());
        JSONObject permissionAssetsResult = doveClient.post("/basic/house/service/permissionAssetsList", http -> {
            JSONObject body = new JSONObject();
            body.put("dataPvType",dataPvType);
            body.put("userId",userLoginInfo.getUserId());
            body.put("departmentNo",userLoginInfo.getDepartmentNo());
            body.put("manageDepartmentNo",userLoginInfo.getManageDepartmentNo());
            body.put("identity",userLoginInfo.getIdentity());
            body.put("roles",userLoginInfo.getRoles());
            body.put("allData", userLoginInfo.isAllData());
            http.setBody(body.toString());
        });
        JSONObject data = permissionAssetsResult.getJSONObject("data");
        if(Objects.nonEmpty(data)){
            JSONArray houseJsonArray = data.getJSONArray("houses");
            JSONArray parkingJsonArray = data.getJSONArray("parkings");
            JSONArray shopJsonArray = data.getJSONArray("shops");
            if (Objects.nonNull(houseJsonArray)) {
                for (Object houseJsonObj : houseJsonArray) {
                    JSONObject houseJson = (JSONObject) houseJsonObj;
                    String id = houseJson.getString("id");
                    result.add(id);
                }
            }
            if (Objects.nonNull(parkingJsonArray)) {
                for (Object parkingJsonObj : parkingJsonArray) {
                    JSONObject parkingJson = (JSONObject) parkingJsonObj;
                    String id = parkingJson.getString("id");
                    result.add(id);
                }
            }
            if (Objects.nonNull(shopJsonArray)) {
                for (Object shopJsonObj : shopJsonArray) {
                    JSONObject shopJson = (JSONObject) shopJsonObj;
                    String id = shopJson.getString("id");
                    result.add(id);
                }
            }
        }
        return result;
    }

    /**
     * 获取业主信息列表
     *
     * @param jsonObject
     * @return
     */
    @HasPermission("crm:resident:view")
    @ReqMapping("/getOwnerList")
    public Page<Resident> getOwnerList(JSONObject jsonObject, Token token) throws Exception {
        //数据权限类型 1.全部业主 2.我管理的业主 3.下属管理的业主
        String dataPvType = jsonObject.getString("dataPvType");
        List<String> bindTypeList = new ArrayList<>();
        bindTypeList.add(BindType.NO_BIND.getId());
        bindTypeList.add(BindType.BIND.getId());
        FindArray<ResidentHouse> findResidentHouse = jdbcSession.findArray(ResidentHouse.class)
                .eq("type", ResidentType.OWNER)
                .in("bindType", bindTypeList)
                .eq("deleted", false)
                .order("createTime", "desc");
        //根据不同类型获取业主的数据权限
        if (Objects.nonEmpty(dataPvType)) {
            List<String> assetsIdList = buildAssetsPv(dataPvType);

            if(Objects.isEmpty(assetsIdList)){
                return new Page<>();
            }

            if(Objects.nonEmpty(assetsIdList)){
                findResidentHouse.in("houseNo",assetsIdList);
            }
        }

        List<ResidentHouse> residentHouseList = findResidentHouse.exe();
        //绑定房屋
        Map<String, String> bindHouse = new HashMap<>();

        //绑定商铺
        Map<String, String> bindShop = new HashMap<>();

        //绑定车位
        Map<String, String> bindParking = new HashMap<>();
        residentHouseList.forEach(v -> {
            HouseType houseType = v.getHouseType();
            String houseName = getFullHouseName(v);
            if (Objects.equal(HouseType.HOUSE.getId(), houseType.getId())) {
                if (bindHouse.containsKey(v.getResidentNo())) {
                    bindHouse.put(v.getResidentNo(), bindHouse.get(v.getResidentNo()) + "," + houseName);
                } else {
                    bindHouse.put(v.getResidentNo(), houseName);
                }
            } else if (Objects.equal(HouseType.SHOP.getId(), houseType.getId())) {
                if (bindShop.containsKey(v.getResidentNo())) {
                    bindShop.put(v.getResidentNo(), bindShop.get(v.getResidentNo()) + "," + houseName);
                } else {
                    bindShop.put(v.getResidentNo(), houseName);
                }
            } else if (Objects.equal(HouseType.PARKING.getId(), houseType.getId())) {
                if (bindParking.containsKey(v.getResidentNo())) {
                    bindParking.put(v.getResidentNo(), bindParking.get(v.getResidentNo()) + "," + houseName);
                } else {
                    bindParking.put(v.getResidentNo(), houseName);
                }
            }
        });

        List<String> ids = residentHouseList.stream().map(ResidentHouse::getResidentNo).collect(Collectors.toList());
        FindPage<Resident> find = jdbcSession.findPage(Resident.class)
                .like(jsonObject, "nickname", "realname", "mobile", "address")
                .in("id", ids)
                .eq("deleted", false)
                .order("createTime", "desc");
        find.page(jsonObject);

        Page<Resident> result = find.exe();
        if (Objects.nonEmpty((result.getList()))) {
            result.getList().forEach(v -> {
                v.setBindHouse(bindHouse.get(v.getId()));
                v.setBindShop(bindShop.get(v.getId()));
                v.setBindParking(bindParking.get(v.getId()));
            });
        }
        return result;
    }


    /**
     * 获取当前登录人否则的楼栋编号
     *
     * @param token 用户信息
     * @return 楼栋编号数组
     * @throws Exception 异常
     */
    public JSONArray getUserBuildNo(Token token, String dataPvType) throws Exception {
        if(Objects.equal(dataPvType,"3")){
            //如果不是上级则放回NULL
            JSONObject employeeResult = doveClient.post("/basic/employee/service/get", (http) -> {
                http.addParam("id", token.getUuid());
            });
            if (Objects.nonNull(employeeResult)) {
                if (employeeResult.getIntValue("code") == 200) {
                    JSONObject employee = employeeResult.getJSONObject("data");
                    JSONObject identityJson = employee.getJSONObject("identity");
                    if(!"1".equals(identityJson.getString("id"))){
                        return null;
                    }
                }
            } else {
                return null;
            }
        }
        JSONArray result = new JSONArray();
        JSONArray buildJsonArray = getBuildByEmployeeNos(token);
        if (Objects.nonNull(buildJsonArray)) {
            for (Object buildJsonObj : buildJsonArray) {
                JSONObject buildJson = (JSONObject) buildJsonObj;
                String id = buildJson.getString("id");
                result.add(id);
            }

        }
        return result;
    }

    /**
     * 获取当前登录人否则的楼栋编号
     *
     * @param token 用户信息
     * @return 楼栋编号数组
     * @throws Exception 异常
     */
    public JSONArray getUserBuildNo(Token token) throws Exception {
        JSONArray result = new JSONArray();
        JSONArray buildJsonArray = getBuildByEmployeeNos(token);
        if (Objects.nonNull(buildJsonArray)) {
            for (Object buildJsonObj : buildJsonArray) {
                JSONObject buildJson = (JSONObject) buildJsonObj;
                String id = buildJson.getString("id");
                result.add(id);
            }

        }
        return result;
    }

    /***
     * 获取当前等于用户管理的楼栋信息
     * @param token 用户信息
     * @return 楼栋集合
     * @throws Exception 异常
     */
    private JSONArray getBuildByEmployeeNos(Token token) throws Exception {
        JSONObject result = doveClient.post("/basic/building/service/list", http -> {
            JSONObject body = new JSONObject();
            body.put("employeeNos", token.getUuid());
            http.addHeader("companyNo", token.getCompanyNo());
            http.setBody(body.toString());
        });

        JSONArray data = result.getJSONArray("data");
        if (Objects.isNull(data)) {
            return null;
        }
        return data;
    }

    /**
     * 获取家属信息列表
     *
     * @param jsonObject
     * @return
     */
    @ReqMapping("/getFriendList")
    public Object getFriendList(JSONObject jsonObject) throws Exception {
        Page<ResidentHouse> page = residentService.getResidentHouseList(jsonObject);
        return Result.success(page);
    }

    /**
     * 获取租客信息列表
     *
     * @param jsonObject
     * @return
     */
    @ReqMapping("/getLesseeList")
    public Object getLesseeList(JSONObject jsonObject) throws Exception {
        Page<ResidentHouse> page = residentService.getResidentHouseList(jsonObject);
        return Result.success(page);
    }


    /**
     * 根据房屋编码获取业主信息
     *
     * @param jsonObject
     * @return
     * @throws Exception
     */
    @ReqMapping("/getOwnerByHouseNo")
    public Object getOwnerByHouseNo(JSONObject jsonObject) throws Exception {
        String houseNo = jsonObject.getString("houseNo");
        if (Objects.isEmpty(houseNo)) {
            return Result.error(1, "房屋编号不能为空.");
        }
        List<String> bindTypeList = new ArrayList<>();
        bindTypeList.add(BindType.NO_BIND.getId());
        bindTypeList.add(BindType.BIND.getId());
        List<ResidentHouse> residentHouseList = jdbcSession.findArray(ResidentHouse.class)
                .eq("type", ResidentType.OWNER)
                .in("bindType", bindTypeList)
                .eq("houseNo", houseNo)
                .eq("deleted", false)
                .order("createTime", "desc")
                .exe();
        if (Objects.nonEmpty(residentHouseList)) {
            ResidentHouse residentHouse = residentHouseList.get(0);
            if (Objects.nonNull(residentHouse)) {
                Resident resident = residentService.getResidentById(residentHouse.getResidentNo());
                residentHouse.setRealname(resident.getRealname());
                residentHouse.setMobile(resident.getMobile());
                residentHouse.setGender(resident.getGender());
                residentHouse.setCardNo(resident.getCardNo());
                residentHouse.setBirthDay(resident.getBirthDay());

                residentHouse.setEmail(resident.getEmail());
                residentHouse.setAddress(resident.getAddress());
                residentHouse.setOfferName(resident.getOfferName());
                residentHouse.setRemark(resident.getRemark());
                return Result.success(residentHouse);
            }
        }
        return Result.success();
    }

    private void buildResidentLesseeAssetsInfo(Resident resident, String residentHouseId) throws Exception {
        List<String> residentHouseIds = new ArrayList<>();
        List<String> assetsIds = new ArrayList<>();
        List<String> assetsNames = new ArrayList<>();
        //住户某一个身份绑定的房屋编号是否认证结果集合
        List<Boolean> authAssetsIds = new ArrayList<>();
        HouseType assetsType = null;
        if (Objects.nonEmpty(residentHouseId)) {
            ResidentHouse residentHouse = residentService.getResidentHouseById(residentHouseId);
            assetsType = residentHouse.getHouseType();
            resident.setHouseType(assetsType);
            String houseName = getFullHouseName(residentHouse);
            residentHouseIds.add(residentHouse.getId());
            assetsIds.add(residentHouse.getHouseNo());
            assetsNames.add(houseName);
            authAssetsIds.add(Objects.equal(residentHouse.getBindType().getId(), BindType.BIND.getId()));
            resident.setStartTime(residentHouse.getStartTime());
            resident.setEndTime(residentHouse.getEndTime());
            //完善住户信息,部分数据已选择的资产信息为准
            resident.setType(ResidentType.LESSEE);
            if (Objects.equal(HouseType.HOUSE.getId(), assetsType.getId())) {
                resident.setHouseNo(residentHouse.getHouseNo());
                resident.setResidentHouseIds(residentHouseIds);
                resident.setHouseIds(assetsIds);
                resident.setHouseNames(assetsNames);
                resident.setAuthHouseIds(authAssetsIds);
            } else if (Objects.equal(HouseType.SHOP.getId(), assetsType.getId())) {
                resident.setShopNo(residentHouse.getHouseNo());
                resident.setResidentShopIds(residentHouseIds);
                resident.setShopIds(assetsIds);
                resident.setShopNames(assetsNames);
                resident.setAuthShopIds(authAssetsIds);
            } else if (Objects.equal(HouseType.PARKING.getId(), assetsType.getId())) {
                resident.setParkingNo(residentHouse.getHouseNo());
                resident.setResidentParkingIds(residentHouseIds);
                resident.setParkingIds(assetsIds);
                resident.setParkingNames(assetsNames);
                resident.setAuthParkingIds(authAssetsIds);
            }
        } else {
            resident.setResidentHouseIds(residentHouseIds);
            resident.setHouseIds(assetsIds);
            resident.setHouseNames(assetsNames);
            resident.setAuthHouseIds(authAssetsIds);

            resident.setResidentShopIds(residentHouseIds);
            resident.setShopIds(assetsIds);
            resident.setShopNames(assetsNames);
            resident.setAuthShopIds(authAssetsIds);

            resident.setResidentParkingIds(residentHouseIds);
            resident.setParkingIds(assetsIds);
            resident.setParkingNames(assetsNames);
            resident.setAuthParkingIds(authAssetsIds);
        }
    }

    private void buildResidentFriendAssetsInfo(Resident resident, String residentHouseId) throws Exception {
        List<String> residentHouseIds = new ArrayList<>();
        List<String> assetsIds = new ArrayList<>();
        List<String> assetsNames = new ArrayList<>();
        //住户某一个身份绑定的房屋编号是否认证结果集合
        List<Boolean> authAssetsIds = new ArrayList<>();
        HouseType assetsType = null;
        if (Objects.nonEmpty(residentHouseId)) {
            ResidentHouse residentHouse = residentService.getResidentHouseById(residentHouseId);
            assetsType = residentHouse.getHouseType();
            resident.setHouseType(assetsType);
            String houseName = getFullHouseName(residentHouse);
            residentHouseIds.add(residentHouse.getId());
            assetsIds.add(residentHouse.getHouseNo());
            assetsNames.add(houseName);
            authAssetsIds.add(Objects.equal(residentHouse.getBindType().getId(), BindType.BIND.getId()));
            resident.setRelationType(residentHouse.getRelationType());
            //完善住户信息,部分数据已选择的资产信息为准
            resident.setType(ResidentType.FRIEND);
            if (Objects.equal(HouseType.HOUSE.getId(), assetsType.getId())) {
                resident.setHouseNo(residentHouse.getHouseNo());
                resident.setResidentHouseIds(residentHouseIds);
                resident.setHouseIds(assetsIds);
                resident.setHouseNames(assetsNames);
                resident.setAuthHouseIds(authAssetsIds);
            } else if (Objects.equal(HouseType.SHOP.getId(), assetsType.getId())) {
                resident.setShopNo(residentHouse.getHouseNo());
                resident.setResidentShopIds(residentHouseIds);
                resident.setShopIds(assetsIds);
                resident.setShopNames(assetsNames);
                resident.setAuthShopIds(authAssetsIds);
            } else if (Objects.equal(HouseType.PARKING.getId(), assetsType.getId())) {
                resident.setParkingNo(residentHouse.getHouseNo());
                resident.setResidentParkingIds(residentHouseIds);
                resident.setParkingIds(assetsIds);
                resident.setParkingNames(assetsNames);
                resident.setAuthParkingIds(authAssetsIds);
            }
        } else {
            resident.setResidentHouseIds(residentHouseIds);
            resident.setHouseIds(assetsIds);
            resident.setHouseNames(assetsNames);
            resident.setAuthHouseIds(authAssetsIds);

            resident.setResidentShopIds(residentHouseIds);
            resident.setShopIds(assetsIds);
            resident.setShopNames(assetsNames);
            resident.setAuthShopIds(authAssetsIds);

            resident.setResidentParkingIds(residentHouseIds);
            resident.setParkingIds(assetsIds);
            resident.setParkingNames(assetsNames);
            resident.setAuthParkingIds(authAssetsIds);
        }
    }

    private void buildResidentOwnerAssetsInfo(Resident resident, String residentHouseId, HouseType assetsType) {
        List<String> residentHouseIds = new ArrayList<>();
        List<String> assetsIds = new ArrayList<>();
        List<String> assetsNames = new ArrayList<>();
        //住户某一个身份绑定的房屋编号是否认证结果集合
        List<Boolean> authAssetsIds = new ArrayList<>();
        List<String> bindTypeList = new ArrayList<>();
        bindTypeList.add(BindType.NO_BIND.getId());
        bindTypeList.add(BindType.BIND.getId());
        FindArray<ResidentHouse> residentAssetsFind = jdbcSession.findArray(ResidentHouse.class)
                .eq("houseType", assetsType)
                .eq("residentNo", resident.getId())
                .eq("type", ResidentType.OWNER)
                .in("bindType", bindTypeList)
                .eq("deleted", false);
        if (Objects.nonEmpty(residentHouseId)) {
            residentAssetsFind.eq("id", residentHouseId);
        }


        List<ResidentHouse> residentAssetsList = residentAssetsFind.exe();
        residentAssetsList.forEach(v -> {
            String houseName = getFullHouseName(v);
            residentHouseIds.add(v.getId());
            assetsIds.add(v.getHouseNo());
            assetsNames.add(houseName);
            authAssetsIds.add(Objects.equal(v.getBindType().getId(), BindType.BIND.getId()));
        });
        resident.setType(ResidentType.OWNER);
        if (Objects.equal(HouseType.HOUSE.getId(), assetsType.getId())) {
            resident.setResidentHouseIds(residentHouseIds);
            resident.setHouseIds(assetsIds);
            resident.setHouseNames(assetsNames);
            resident.setAuthHouseIds(authAssetsIds);
        } else if (Objects.equal(HouseType.SHOP.getId(), assetsType.getId())) {
            resident.setResidentShopIds(residentHouseIds);
            resident.setShopIds(assetsIds);
            resident.setShopNames(assetsNames);
            resident.setAuthShopIds(authAssetsIds);
        } else if (Objects.equal(HouseType.PARKING.getId(), assetsType.getId())) {
            resident.setResidentParkingIds(residentHouseIds);
            resident.setParkingIds(assetsIds);
            resident.setParkingNames(assetsNames);
            resident.setAuthParkingIds(authAssetsIds);
        }
    }

    /**
     * 根据条件获取一条住户信息
     *
     * @param jsonObject 条件
     * @return 住户信息
     * @throws Exception 异常
     */
    @HasPermission("crm:resident:view")
    @ReqMapping("/getResident")
    public Object getResident(JSONObject jsonObject) throws Exception {
        String cardNo = jsonObject.getString("cardNo");
        String mobile = jsonObject.getString("mobile");
        //住户类型
        String type = jsonObject.getString("type");
        String id = jsonObject.getString("id");
        if (Objects.isEmpty(id) && Objects.isEmpty(mobile)) {
            return Result.success();
        }
        //住户房屋关系编号
        String residentHouseId = jsonObject.getString("residentHouseId");

        FindOne<Resident> find = jdbcSession.findOne(Resident.class)
                .eq(jsonObject, "id");

        if (Objects.nonEmpty(cardNo) || Objects.nonEmpty(mobile)) {
            find.markBegin();
            //find.eq("cardNo", cardNo).or();
            find.eq("mobile", mobile).or();
            find.markEnd().and();
        }
        Resident resident = find.exe();
        if (Objects.nonNull(resident) && Objects.nonNull(type)) {
            if (Objects.equal(type, ResidentType.OWNER.getId())) {
                buildResidentOwnerAssetsInfo(resident, residentHouseId, HouseType.HOUSE);
                buildResidentOwnerAssetsInfo(resident, residentHouseId, HouseType.SHOP);
                buildResidentOwnerAssetsInfo(resident, residentHouseId, HouseType.PARKING);
            } else if (Objects.equal(type, ResidentType.FRIEND.getId())) {
                buildResidentFriendAssetsInfo(resident, residentHouseId);
            } else if (Objects.equal(type, ResidentType.LESSEE.getId())) {
                buildResidentLesseeAssetsInfo(resident, residentHouseId);
            }
        }
        return Result.success(resident);
    }

    private String getFullHouseName(ResidentHouse residentHouse) {
        StringBuilder sb = new StringBuilder();
        String buildName = Objects.isEmpty(residentHouse.getBuildName()) ? "" : residentHouse.getBuildName();
        String unitName = Objects.isEmpty(residentHouse.getUnitName()) ? "" : residentHouse.getUnitName();
        String floorName = Objects.isEmpty(residentHouse.getFloorName()) ? "" : residentHouse.getFloorName();
        sb.append(residentHouse.getCommunityName()).append(">").append(buildName).append(unitName).append(">").append(floorName).append(residentHouse.getHouseName());
        return sb.toString();
    }

    /***
     * 根据条件删除住户房屋
     * 1.业主列表删除
     * 2.亲属列表删除
     * 3.租户列表删除
     * @param jsonObject 查询条件
     * @return 操作结果
     * @throws Exception 操作异常
     */
    //@HasPermission("crm:residentHouse:edit")
    @ReqMapping("/deleteResidentHouse")
    public Object deleteResidentHouse(JSONObject jsonObject) throws Exception {
        residentService.deleteResidentHouse(jsonObject);
        return Result.success();
    }


    /**
     * 批量删除用户资产绑定信息
     * @param jsonObject
     * @return
     * @throws Exception
     */
    @ReqMapping("/batchDeleteResidentHouse")
    public Object batchDeleteResidentHouse(JSONObject jsonObject) throws Exception {
        JSONArray assetsList=jsonObject.getJSONArray("assetsList");
        if (Objects.nonEmpty(assetsList)) {
            for (Object assetsObj : assetsList) {
                JSONObject assets = (JSONObject) assetsObj;
                residentService.deleteResidentHouse(assets);
            }
        }
        return Result.success();
    }

    /**
     * 根据条件导出业主数据
     *
     * @param jsonObject 条件对象
     * @return 文件
     * @throws Exception 异常
     */
    @ReqMapping("/exportOwnerData")
    public Object exportOwnerData(JSONObject jsonObject, Token token) throws Exception {
        jsonObject.put("pageNo", 1);
        jsonObject.put("pageSize", Short.MAX_VALUE);
        Page<Resident> page = getOwnerList(jsonObject, token);
        File dataFile = exportOwnerDataFile(page.getList());
        return Result.download(dataFile);
    }

    private File exportOwnerDataFile(List<Resident> residentList) throws Exception {
        Workbook wb = exportOwnerWorkBook(residentList);
        return ExcelUtil.writeXlsFile(wb, "业主列表", ".xls");
    }


    private Workbook exportOwnerWorkBook(List<Resident> residentList) {

        // 生成模板文件
        HSSFWorkbook wb = new HSSFWorkbook();
        //创建工具
        CreationHelper helper = wb.getCreationHelper();
        //单元格样式类
        CellStyle dateCellStyle = wb.createCellStyle();
        //设置单元格格式
        dateCellStyle.setDataFormat(helper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));

        Sheet sheet = wb.createSheet();
        Row headerRow = sheet.createRow(0);
        int headerCellNum = 0;
        String[] chargeUserInstrument = {"业主姓名", "手机号码", "绑定房屋", "添加时间"};
        for (String s : chargeUserInstrument) {
            Cell cell = headerRow.createCell(headerCellNum++);
            cell.setCellValue(s);
        }

        int cellNum = 0;
        for (int i = 0; i < residentList.size(); i++) {
            Resident resident = residentList.get(i);
            Row row = sheet.createRow(i + 1);
            cellNum = 0;
            row.createCell(cellNum++).setCellValue(resident.getRealname());
            row.createCell(cellNum++).setCellValue(resident.getMobile());
            row.createCell(cellNum++).setCellValue(resident.getBindHouse());

            Cell tmpCell = row.createCell(cellNum++);
            tmpCell.setCellStyle(dateCellStyle);
            tmpCell.setCellValue(resident.getCreateTime());
        }

        // 自动列宽
        for (int i = 0; i < cellNum; i++) {
            if (i == 0) {
                // id列不调整
                continue;
            }
            // 自动列宽
            ExcelUtil.autoSizeColumn(sheet, i);
        }
        return wb;
    }

    /**
     * 根据条件导出家属数据
     *
     * @param jsonObject 条件对象
     * @return 文件
     * @throws Exception 异常
     */
    @ReqMapping("/exportFriendData")
    public Object exportFriendData(JSONObject jsonObject,Token token) throws Exception {
        jsonObject.put("pageNo", 1);
        jsonObject.put("pageSize", Short.MAX_VALUE);
        Page<ResidentHouse> page = getResidentHouseList(jsonObject,token);
        File dataFile = exportFriendDataFile(page.getList());
        return Result.download(dataFile);
    }

    private File exportFriendDataFile(List<ResidentHouse> residentHouseList) throws Exception {
        Workbook wb = exportFriendWorkBook(residentHouseList);
        return ExcelUtil.writeXlsFile(wb, "家属列表", ".xls");
    }

    private String formatTimeToStr(LocalDateTime localDateTime, String pattern) {
        if (Objects.isNull(localDateTime)) {
            return "";
        }
        return DateTimeFormatter.ofPattern(pattern).format(localDateTime);
    }

    private Workbook exportFriendWorkBook(List<ResidentHouse> residentHouseList) {

        // 生成模板文件
        HSSFWorkbook wb = new HSSFWorkbook();
        //创建工具
        CreationHelper helper = wb.getCreationHelper();
        //单元格样式类
        CellStyle dateCellStyle = wb.createCellStyle();
        //设置单元格格式
        dateCellStyle.setDataFormat(helper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));

        Sheet sheet = wb.createSheet();
        Row headerRow = sheet.createRow(0);
        int headerCellNum = 0;
        String[] chargeUserInstrument = {"家属姓名", "手机号码", "类型", "绑定房屋", "业主", "与业主的关系", "状态", "时间", "创建时间"};
        for (String s : chargeUserInstrument) {
            Cell cell = headerRow.createCell(headerCellNum++);
            cell.setCellValue(s);
        }

        int cellNum = 0;
        for (int i = 0; i < residentHouseList.size(); i++) {
            ResidentHouse residentHouse = residentHouseList.get(i);
            String houseName = getFullHouseName(residentHouse);
            StringBuilder time = new StringBuilder();
            if (Objects.equal(residentHouse.getBindType().getId(), BindType.BIND.getId())) {
                time.append("绑定时间:").append(formatTimeToStr(residentHouse.getBindTime(), "yyyy-MM-dd HH:mm:ss"));
            } else if (Objects.equal(residentHouse.getBindType().getId(), BindType.UN_BIND.getId())) {
                time.append("绑定时间:").append(formatTimeToStr(residentHouse.getBindTime(), "yyyy-MM-dd HH:mm:ss")).append(";解绑时间:").append(formatTimeToStr(residentHouse.getUnBindTime(), "yyyy-MM-dd HH:mm:ss"));
            } else if (Objects.equal(residentHouse.getBindType().getId(), BindType.INVALID.getId())) {
                time.append("失效时间:").append(formatTimeToStr(residentHouse.getUnBindTime(), "yyyy-MM-dd HH:mm:ss"));
            }
            Row row = sheet.createRow(i + 1);
            cellNum = 0;
            row.createCell(cellNum++).setCellValue(residentHouse.getRealname());
            row.createCell(cellNum++).setCellValue(residentHouse.getMobile());
            row.createCell(cellNum++).setCellValue(residentHouse.getHouseType().getDesc());
            row.createCell(cellNum++).setCellValue(houseName);
            row.createCell(cellNum++).setCellValue(residentHouse.getPname());
            row.createCell(cellNum++).setCellValue(residentHouse.getRelationType().getDesc());
            row.createCell(cellNum++).setCellValue(residentHouse.getBindType().getDesc());
            row.createCell(cellNum++).setCellValue(time.toString());
            Cell tmpCell = row.createCell(cellNum++);
            tmpCell.setCellStyle(dateCellStyle);
            tmpCell.setCellValue(residentHouse.getCreateTime());
        }

        // 自动列宽
        for (int i = 0; i < cellNum; i++) {
            if (i == 0) {
                // id列不调整
                continue;
            }
            // 自动列宽
            ExcelUtil.autoSizeColumn(sheet, i);
        }
        return wb;
    }

    /**
     * 根据条件导出家属数据
     *
     * @param jsonObject 条件对象
     * @return 文件
     * @throws Exception 异常
     */
    @ReqMapping("/exportLesseeData")
    public Object exportLesseeData(JSONObject jsonObject,Token token) throws Exception {
        jsonObject.put("pageNo", 1);
        jsonObject.put("pageSize", Short.MAX_VALUE);
        Page<ResidentHouse> page = (Page<ResidentHouse>) getResidentHouseList(jsonObject,token);
        File dataFile = exportLesseeDataFile(page.getList());
        return Result.download(dataFile);
    }

    private File exportLesseeDataFile(List<ResidentHouse> residentHouseList) throws Exception {
        Workbook wb = exportLesseeWorkBook(residentHouseList);
        return ExcelUtil.writeXlsFile(wb, "租客列表", ".xls");
    }


    private Workbook exportLesseeWorkBook(List<ResidentHouse> residentHouseList) {

        // 生成模板文件
        HSSFWorkbook wb = new HSSFWorkbook();
        //创建工具
        CreationHelper helper = wb.getCreationHelper();
        //单元格样式类
        CellStyle dateCellStyle = wb.createCellStyle();
        //设置单元格格式
        dateCellStyle.setDataFormat(helper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));

        Sheet sheet = wb.createSheet();
        Row headerRow = sheet.createRow(0);
        int headerCellNum = 0;
        String[] chargeUserInstrument = {"租户姓名", "手机号码", "类型", "租赁房屋", "租赁时间", "出租人", "状态", "时间", "创建时间"};
        for (String s : chargeUserInstrument) {
            Cell cell = headerRow.createCell(headerCellNum++);
            cell.setCellValue(s);
        }

        int cellNum = 0;
        for (int i = 0; i < residentHouseList.size(); i++) {
            ResidentHouse residentHouse = residentHouseList.get(i);
            String houseName = getFullHouseName(residentHouse);
            StringBuilder time = new StringBuilder();
            if (Objects.equal(residentHouse.getBindType().getId(), BindType.BIND.getId())) {
                time.append("绑定时间:").append(formatTimeToStr(residentHouse.getBindTime(), "yyyy-MM-dd HH:mm:ss"));
            } else if (Objects.equal(residentHouse.getBindType().getId(), BindType.UN_BIND.getId())) {
                time.append("绑定时间:").append(formatTimeToStr(residentHouse.getBindTime(), "yyyy-MM-dd HH:mm:ss")).append(";解绑时间:").append(formatTimeToStr(residentHouse.getUnBindTime(), "yyyy-MM-dd HH:mm:ss"));
            } else if (Objects.equal(residentHouse.getBindType().getId(), BindType.INVALID.getId())) {
                time.append("失效时间:").append(formatTimeToStr(residentHouse.getUnBindTime(), "yyyy-MM-dd HH:mm:ss"));
            }
            Row row = sheet.createRow(i + 1);
            cellNum = 0;
            row.createCell(cellNum++).setCellValue(residentHouse.getRealname());
            row.createCell(cellNum++).setCellValue(residentHouse.getMobile());
            row.createCell(cellNum++).setCellValue(residentHouse.getHouseType().getDesc());
            row.createCell(cellNum++).setCellValue(houseName);
            row.createCell(cellNum++).setCellValue(formatTimeToStr(residentHouse.getStartTime(), "yyyy-MM-dd") + " 至 " + formatTimeToStr(residentHouse.getEndTime(), "yyyy-MM-dd"));
            row.createCell(cellNum++).setCellValue(residentHouse.getPname());
            row.createCell(cellNum++).setCellValue(residentHouse.getBindType().getDesc());
            row.createCell(cellNum++).setCellValue(time.toString());
            Cell tmpCell = row.createCell(cellNum++);
            tmpCell.setCellStyle(dateCellStyle);
            tmpCell.setCellValue(residentHouse.getCreateTime());
        }

        // 自动列宽
        for (int i = 0; i < cellNum; i++) {
            if (i == 0) {
                // id列不调整
                continue;
            }
            // 自动列宽
            ExcelUtil.autoSizeColumn(sheet, i);
        }
        return wb;
    }


    public List<String> getChildDepartments(List<String> departments) throws Exception {
        JSONObject result = doveClient.post("/basic/department/service/getChildDepartments", http->{
            JSONObject body = new JSONObject();
            body.put("pidList", departments);
            http.setBody(body.toString());
        });

        if (result.getIntValue("code") == 200) {
            JSONArray data = result.getJSONArray("data");
            if(Objects.nonEmpty(data)){
                return JSONObject.parseArray(data.toJSONString(), String.class);
            }
        }
        return new ArrayList<>();
    }

}
